/**
 * 
 */
package view;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Font;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;

import model.GameDriver;
import model.State;
import model.StateObserver;

import common.DataManager;

import controller.TickObserver;

/**
 * @author Bill Heys - 201031705
 *
 *This is the main JFrame for the game.
 *It contains inner panels which correspond to the appropriate views, 
 *as determined by the GameDriver class in the model.
 */
public class Frame extends JFrame implements StateObserver, TickObserver{
	
	private static JPanel cards = new JPanel(new CardLayout());
	private GameDriver gameDriver = new GameDriver();
	private GamePanel gamePanel;
	private MainMenuPanel mainMenuPanel;
	private HowToPlayPanel howToPlayPanel;
	
	/**
	 * Constructs the frame with it's subcomponents and displays it
	 */
	public Frame(){
		super("Zombosaur Defence");
		
		//Font Stuff
		InputStream in = this.getClass().getResourceAsStream("/graphics/Herculanum.ttf");
		Font font = null;
	    try{
		font = Font.createFont(Font.TRUETYPE_FONT, in);
	    } catch (Exception ex) {
	      ex.printStackTrace();
	      System.err.println("Herculanum.ttf" + " not loaded.  Using serif font.");
	      font = new Font("serif", Font.PLAIN, 20);
	    }
	    
	    Enumeration keys = UIManager.getDefaults().keys();
	    while (keys.hasMoreElements()) {
	      Object key = keys.nextElement();
	      Object value = UIManager.get (key);
	      if (value != null && value instanceof javax.swing.plaf.FontUIResource)
	        UIManager.put (key, new FontUIResource("Herculanum", font.BOLD, 20));
	      }
		//
	    
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		cards.setBackground(Color.GREEN);
        		
		gamePanel = new GamePanel(gameDriver.getMap().getTrailCoordinates(), this.gameDriver); 
		mainMenuPanel = new MainMenuPanel();
		howToPlayPanel = new HowToPlayPanel();
		
		cards.add(mainMenuPanel, DataManager.MAIN_MENU_PANEL_NAME);
		cards.add(gamePanel, DataManager.GAME_PANEL_NAME);
		cards.add(howToPlayPanel, DataManager.HOW_TO_PLAY_PANEL_NAME);
		cards.setSize(cards.getPreferredSize());
		
		this.getContentPane().add(cards);
		
		System.out.println("getParent() " + SwingUtilities.getWindowAncestor(cards).getName());
		//attach to model
		gameDriver.addStateObserver(this);
		
		//Display the window.
		this.setResizable(false);
		this.pack();
        this.setVisible(true);
	}
	
	public static JPanel getCards(){
		return cards;
	}
	
	/**
     * Get all the necessary data from the map in the model,
     * and update the view 
     */
	@Override
	public void onTick(int tickCount) {
		gameDriver.getMap().onTick(tickCount);
		gamePanel.getMapPanel().tickUpdate(gameDriver);
	}
	
	/**
	 * updates all the components on the frame with data from the model
	 */
	public void updateGamePanel(){
		this.gamePanel.updateChildren(this.gameDriver);
	}

	/**
	 * Method inherited from the StateObserver Interface.
	 * Given the new state, it displays the desired panel.
	 */
	@Override
	public void gameStateChanged(State newState) {
		String panelName = DataManager.getPanelNameFromState(newState);
		assert(panelName != "NULL");
		System.out.println(newState.getStateName()+" "+panelName);
		CardLayout cardLayout = (CardLayout)cards.getLayout();
		cardLayout.show(cards, panelName);
		if(newState.getStateName() == "SETUP_STAGE_STATE"){
			gamePanel.beginSetup(this.gameDriver);
		}
		else if (newState.getStateName() == "ATTACK_STAGE_STATE"){
			gamePanel.beginAttack(this.gameDriver);
		}
		
	}
	
	public GamePanel getGamePanel(){
		return gamePanel;
	}
	public void setGamePanel(GamePanel panel){
		 this.gamePanel = panel;
	}
	public MainMenuPanel getMainMenuPanel(){
		return mainMenuPanel;
	}
	public void setMainMenuPanel(MainMenuPanel panel){
		 this.mainMenuPanel = panel;
	}

	public GameDriver getGameDriver(){
		return this.gameDriver;
	}
	
	public void setGameDriver(GameDriver gameDriver){
		this.gameDriver = gameDriver;
	}
}
